Skip to content

fix(integrations): preserve native skill invocation prefixes#3663

Open
BenBtg wants to merge 19 commits into
mainfrom
fix/native-invocation-prefixes
Open

fix(integrations): preserve native skill invocation prefixes#3663
BenBtg wants to merge 19 commits into
mainfrom
fix/native-invocation-prefixes

Conversation

@BenBtg

@BenBtg BenBtg commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Preserve each integration's native skill invocation syntax when rendering command references:

  • render Codex and ZCode skill invocations as $speckit-<name>
  • retain /speckit-<name> for other skills integrations and /speckit.<name> for command integrations
  • propagate the selected prefix through init, install, switch, upgrade, refresh, extension registration, preset restoration, and shared Bash/PowerShell/Python helpers
  • keep literal documentation examples unchanged while resolving explicit command-reference tokens
  • centralize integration prefix selection to avoid duplicated branching across lifecycle paths

This extracts the invocation-prefix work from #3616 so that PR remains focused on the constitution command guardrail. No constitution template or guardrail test changes are included here.

Validation

  • .venv/bin/python -m pytest tests/integrations/test_base.py tests/integrations/test_cli.py tests/integrations/test_integration_codex.py tests/integrations/test_integration_zcode.py tests/integrations/test_integration_subcommand.py tests/test_extensions.py tests/test_presets.py tests/test_setup_tasks.py -q — 1151 passed
  • uvx ruff check src/specify_cli tests/integrations/test_integration_codex.py tests/integrations/test_integration_zcode.py --quiet
  • git diff --check

Authored autonomously by GitHub Copilot (model: GPT-5.6 Sol) on behalf of @BenBtg.

BenBtg added 11 commits July 22, 2026 18:25
Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Resolve generated command references with the active agent prefix instead of rewriting all slash-form text during post-processing.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Pass dollar-style skill prefixes through bare-project integration installation and cover the shared template output.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Use agent-native invocation prefixes in extension command registration and dynamic shared-script command hints.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Escape dollar-prefixed commands embedded in Bash strings and propagate the native prefix into installed Python command helpers.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Rewrite installed Bash and PowerShell formatter return expressions so direct callers receive the selected integration's native prefix.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Describe hook-derived references as command invocations so dollar-prefixed skills do not receive contradictory slash-command terminology.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 02f9e138-da58-4a60-93b9-eae659d2aa19
Copilot AI review requested due to automatic review settings July 22, 2026 17:30
@BenBtg
BenBtg requested a review from mnriem as a code owner July 22, 2026 17:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Preserves native $speckit-* invocation syntax for Codex and ZCode across integration rendering and lifecycle operations.

Changes:

  • Centralizes native prefix resolution.
  • Propagates prefixes through shared infrastructure, extensions, presets, and integration lifecycle flows.
  • Adds coverage for dollar-prefixed rendering across Bash, PowerShell, and Python.
Show a summary per file
File Description
src/specify_cli/__init__.py Forwards invocation prefixes to shared infrastructure.
src/specify_cli/agents.py Applies native prefixes during command registration.
src/specify_cli/commands/init.py Supplies the selected prefix during initialization.
src/specify_cli/integration_runtime.py Resolves prefixes by integration mode.
src/specify_cli/integrations/_helpers.py Preserves prefixes when changing defaults.
src/specify_cli/integrations/_install_commands.py Handles prefixes during installation.
src/specify_cli/integrations/_migrate_commands.py Handles prefixes during switch and upgrade.
src/specify_cli/integrations/base.py Renders native skill invocations and hook guidance.
src/specify_cli/presets/__init__.py Preserves prefixes during preset restoration.
src/specify_cli/shared_infra.py Renders prefixes in templates and scripts.
tests/integrations/test_base.py Tests core invocation rendering.
tests/integrations/test_cli.py Tests shared template and script output.
tests/integrations/test_integration_base_skills.py Updates hook-guidance expectations.
tests/integrations/test_integration_codex.py Verifies Codex guidance wording.
tests/integrations/test_integration_subcommand.py Tests install and switch behavior.
tests/integrations/test_integration_zcode.py Cleans up ZCode test formatting.
tests/test_extensions.py Tests Codex extension references.
tests/test_presets.py Tests dollar-prefixed preset restoration.
tests/test_setup_tasks.py Tests Bash and PowerShell formatters.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 19/19 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/base.py Outdated
Comment thread src/specify_cli/presets/__init__.py Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 17:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 19/19 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread src/specify_cli/integration_runtime.py Outdated
Comment thread src/specify_cli/shared_infra.py
- Add SKILL_COLON_AGENTS frozenset and get_invocation_prefix() to
  _invocation_style.py so Kimi resolves to '/skill:' in skills mode
- Switch invoke_prefix_for_integration() to use get_invocation_prefix()
  instead of the binary dollar/slash check
- Update post_process_skill_content docstring (base.py) to cover both
  slash and dollar native invocation forms
- Update _resolve_command_refs_in_skill docstring (presets/__init__.py)
  to document the dollar-prefixed result alongside slash forms

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/agents.py Outdated
Replace the binary is_dollar_skills_agent ternary with get_invocation_prefix
so that __SPECKIT_COMMAND_*__ tokens in Kimi skill files resolve to
/skill:speckit-<name> rather than /speckit-<name>.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:08
Comment thread src/specify_cli/agents.py Fixed
Leftover from replacing the inline ternary with get_invocation_prefix.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

Copilot AI review requested due to automatic review settings July 23, 2026 00:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/base.py Outdated
…ntent

Replaces the binary is_dollar_skills_agent ternary with get_invocation_prefix
so that Kimi's hook-command note is injected as /skill:speckit-git-commit from
the start. This keeps _inject_hook_command_note idempotent for Kimi: the
previous note with its native prefix now matches on repeated passes, preventing
duplicate note injection.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/base.py:854

  • This still special-cases only dollar-style skills instead of using the new native-prefix resolver. For Kimi, the token is first rendered as /speckit-*, so KimiIntegration.post_process_skill_content() must broadly replace every /speckit-*; that also rewrites literal documentation examples, contrary to the PR’s stated token-only behavior. Resolve the token with get_invocation_prefix() here and narrow/remove Kimi’s broad replacement.
        invocation_prefix = (
            "$"
            if is_dollar_skills_agent(agent_name, invoke_separator == "-")
            else "/"
        )
  • Files reviewed: 20/20 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread src/specify_cli/presets/__init__.py Outdated
Comment thread tests/test_presets.py Outdated
Replace the binary is_dollar_skills_agent ternary with get_invocation_prefix
so Kimi tokens resolve to /skill:speckit-* directly rather than /speckit-*
(which previously relied on the broad post-process body replacement).

Also fix test_restore_skill_preserves_dollar_command_refs to write raw_core
with the unresolved __SPECKIT_COMMAND_PLAN__ token, exercising the resolver
rather than bypassing it with a pre-resolved string.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/base.py:854

  • This path still only recognizes dollar-style skills, so Kimi command tokens are first rendered as /speckit-* and are then corrected by KimiIntegration.post_process_skill_content()'s whole-body replacement (integrations/kimi/__init__.py:60-63). That replacement also changes literal /speckit-* documentation examples, contradicting this PR's stated token-only behavior; the same happens for extension/preset skill bodies that call the Kimi post-processor. Resolve the prefix here with get_invocation_prefix(agent_name, invoke_separator == "-"), and narrow/remove Kimi's broad replacement now that explicit tokens and hook notes can be rendered natively.
        invocation_prefix = (
            "$"
            if is_dollar_skills_agent(agent_name, invoke_separator == "-")
            else "/"
        )
  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/presets/__init__.py Outdated
Add /skill:speckit-<cmd> to the docstring so the contract covers all
three native prefix forms returned by get_invocation_prefix.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/_invocation_style.py
- test_skill_colon_prefix_core_command: resolve_command_refs with /skill: prefix
- test_get_invocation_prefix_skill_colon: get_invocation_prefix returns /skill:
  for kimi (skills), / for kimi (non-skills), $ for codex, / for claude
- test_kimi_skill_post_processing_is_idempotent: verifies Kimi's hook-command
  note is injected with /skill: prefix and does not duplicate on re-runs
- test_installed_bash_formatter_uses_skill_colon_prefix: shared-infra bash
  formatter outputs /skill:speckit-plan when installed with /skill: prefix

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 65ef91d9-4c31-4f31-a009-ed2093fe7f28
Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Copilot AI review requested due to automatic review settings July 23, 2026 00:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/base.py:853

  • Use the centralized prefix resolver here as well. For Kimi this currently renders explicit tokens as /speckit-* and relies on KimiIntegration.post_process_skill_content()'s whole-body replacement to obtain /skill:speckit-*; that replacement also changes literal /speckit-* documentation, contradicting the PR's token-only behavior. Resolve the token directly with get_invocation_prefix(agent_name, invoke_separator == "-") and remove/narrow Kimi's broad replacement.
        invocation_prefix = (
            "$"
            if is_dollar_skills_agent(agent_name, invoke_separator == "-")
            else "/"
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants